// DebugData.cpp: implementation of the CDebugData class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "8085.h"
#include "DebugData.h"
#include "MyException.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDebugData::CDebugData() :m_cAddrToSrc(4*1024),m_cSrcToAddr(4*1024)
{
    m_pFile = NULL;
    m_cAddrToSrc.RemoveAll();
    m_cSrcToAddr.RemoveAll();
}

CDebugData::~CDebugData()
{
    Close();
}

void CDebugData::Open(char *szFileName,char *mode)
{
    Close(); // close any existing open files
    if(strlen(szFileName)==0)
    {
        throw CMyException(severe,empty_file_name,
            "CdebugData::Empty file name");
    }
    if(NULL==(m_pFile=fopen(szFileName,mode)))
    {
        char szError[1024];
        sprintf(szError,"CdebugData::Error could not open debug info file <%s>",
            szFileName);
        throw CMyException(severe,file_open_error,szError);
    }
}

void CDebugData::Close()
{
    if(m_pFile)
        fclose(m_pFile);    
    m_pFile = NULL;
    // clean up the hash table
    m_cAddrToSrc.RemoveAll();
    m_cSrcToAddr.RemoveAll();
}

// first parameter is the memory address and second the corresponding
// source line number
void CDebugData::Write(word nAddress, int nSrcLine)
{
    fprintf(m_pFile,"%d %d ",nAddress,nSrcLine);
}


// read the entire debug infor and create a hash table
void CDebugData::Read()
{
    // optimize, enhance , currently it takes a very long time to create 
    // the Hash tables,  One solution is to read only what is necessary
    // say 100 instructions and the corresponding source line.
    word nAddress;
    unsigned nSrcLine;
    while(fscanf(m_pFile,"%d %d",&nAddress,&nSrcLine)!=EOF)
    {
        m_cAddrToSrc.SetAt(nAddress,nSrcLine);
        m_cSrcToAddr.SetAt(nSrcLine,nAddress);
    }
}

// given an 8085 memory address find the source line number
unsigned CDebugData::GetSourceLine(word address)
{
    unsigned nSrcLine;
    if(m_cAddrToSrc.Lookup(address,nSrcLine))
        return nSrcLine;
    // no source line equivalent for the given address
    throw CMyException(noerror,no_source_equivalent,
        "No equivalent source line");
}


BOOL CDebugData::GetSourceLine(word address, unsigned int &line)
{
    if(m_cAddrToSrc.Lookup(address,line))
        return TRUE;
	return FALSE;
}

// given the source line number return the address in 8085 memory
// that it translates to.
word CDebugData::GetMemoryAddress(unsigned int nSrcLine)
{
    word nAddress;
    if(m_cSrcToAddr.Lookup(nSrcLine,nAddress))
        return nAddress;
    CString str;
    str.Format("Source Line %d has No equivalent 8085 memory address",nSrcLine);
    // no source line equivalent for the given address
    throw CMyException(noerror,no_source_equivalent,str);
}
